package com.example.forum.services.impl;

import com.example.forum.common.AppResult;
import com.example.forum.common.ResultCode;
import com.example.forum.dao.UserMapper;
import com.example.forum.exception.ApplicationException;
import com.example.forum.model.User;
import com.example.forum.services.IUserService;
import com.example.forum.utils.MD5Util;
import com.example.forum.utils.StringUtil;
import com.example.forum.utils.UUIDUtil;
import com.example.forum.utils.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.UUID;

@Slf4j
@Service
public class UserServiceImpl implements IUserService {
    @Autowired
    private UserMapper userMapper;

    //  从配置中读取头像保存地址
    //  从配置中读取头像保存地址
    @Value("${forum.avatarPath}")
    private String avatarPath;

    @Override
    public void createNormalUser(User user) {
        //  1. 参数校验
        if(user == null) {
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }

        //  2. 查询用户是否存在
        User exitUser = userMapper.selectByUsername(user.getUsername());
        if(exitUser != null) {
            //  记录日志
            log.info(ResultCode.AILED_USER_EXISTS.getMessage() + "username= " + user.getUsername());
            throw new ApplicationException(AppResult.failed(ResultCode.AILED_USER_EXISTS));
        }
        //  设置默认属性
        UserUtil.setUserDefaultValue(user);

        int row = userMapper.insertSelective(user);
        if(row != 1) {
            log.error(ResultCode.FAILED_CREATE.getMessage() + "username= " + user.getUsername());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));
        }
        log.info("新增用户成功： username= " + user.getUsername());

    }


    @Override
    public User selectByUsername(String username) {
        //  1. 参数校验
        if(StringUtil.isEmpty(username)) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.getMessage() + ": 参数为空");
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //  2. 调用 mapper
        return userMapper.selectByUsername(username);
    }

    @Override
    public User login(String username, String password) {
        //  1. 参数校验
        if(StringUtil.isEmpty(username) || StringUtil.isEmpty(password)) {
            log.warn(ResultCode.FAILED_LOGIN.getMessage());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN));
        }
        //  2. 查询
        User user = selectByUsername(username);
        if(user == null) {
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN));
        }
        //  3. 密码比对
        if(!MD5Util.verifyOriginalAndCiphertext(password,user.getSalt(),user.getPassword())) {
            log.error(ResultCode.FAILED_LOGIN.getMessage() + "密码错误, username = " + username);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN));
        }
        //  4. 返回
        log.info("登录成功: username = " + username);
        return user;
    }


    @Override
    public User selectById(Long id) {
        if(id == null) {
            log.warn(ResultCode.ERROR_IS_NULL.getMessage());
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));
        }
        return userMapper.selectByPrimaryKey(id);
    }

    @Override
    public void addOneArticleCountById(Long id) {
        if(id == null || id <= 0) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.getMessage());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }

        User user = userMapper.selectByPrimaryKey(id);
        if(user == null) {
            log.warn(ResultCode.ERROR_IS_NULL.getMessage());
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));
        }

        //  拼装数据
        User updateUser = new User();
        updateUser.setId(id);
        updateUser.setArticleCount(user.getArticleCount() + 1);

        //  检验结果
        int ret =  userMapper.updateByPrimaryKeySelective(updateUser);
        if(ret != 1) {
            log.warn(ResultCode.FAILED.getMessage());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }
    }

    @Override
    public void subOneArticleCountById(Long id) {
        if(id == null || id <= 0) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE.getMessage());
        }
        User user = userMapper.selectByPrimaryKey(id);
        if(user == null || user.getDeleteState() == 1) {
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            throw new ApplicationException(ResultCode.FAILED_USER_NOT_EXISTS.getMessage());
        }
        //  重新组装数据
        User updateUser = new User();
        updateUser.setId(id);
        if(user.getArticleCount() == 0) {
            updateUser.setArticleCount(0);
        }
        else {
            updateUser.setArticleCount(user.getArticleCount() - 1);
        }
        //  调用mapper
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        if(row != 1) {
            log.warn(ResultCode.FAILED.toString() + "更新数据失败");
            throw new ApplicationException(ResultCode.FAILED.getMessage());
        }
        log.info("更新成功. user.id = " + user.getId());
    }

    @Override
    public void modifyInfo(User user) {
        //  1. 参数校验
        if(user == null || user.getId() == null || user.getId() <= 0) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE.getMessage());
        }

        //  2. 检验用户是否存在
        User exitsUser = userMapper.selectByPrimaryKey(user.getId());
        if(exitsUser == null) {
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            throw new ApplicationException(ResultCode.FAILED_USER_NOT_EXISTS.getMessage());
        }

        //  3.组装数据
        User updateUser = new User();
        updateUser.setId(exitsUser.getId());
        updateUser.setNickname(user.getNickname());
        updateUser.setEmail(user.getEmail());
        updateUser.setPhoneNum(user.getPhoneNum());
        updateUser.setRemark(user.getRemark());
        updateUser.setUpdateTime(new Date());
        //  3.1 昵称设置默认值
        //  设置默认值时，对比数据库中的数据，这样可以减少数据库修改次数
        if(StringUtil.isEmpty(user.getNickname())) {
            updateUser.setNickname(exitsUser.getNickname());
        }
        //  3.2 邮箱设置默认值
        if(StringUtil.isEmpty(user.getEmail())) {
            updateUser.setEmail(exitsUser.getEmail());
        }
        //  3.3 电话设置默认值
        if(StringUtil.isEmpty(user.getPhoneNum())) {
            updateUser.setPhoneNum(exitsUser.getPhoneNum());
        }
        //  3.4 简介设置默认值
        if(StringUtil.isEmpty(user.getRemark())) {
            updateUser.setRemark(exitsUser.getRemark());
        }

        //  4. 调用 mapper
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        if(row != 1) {
            log.warn(ResultCode.FAILED.toString() + ". 更新数据库失败 user.id = " + user.getId());
            throw new ApplicationException(ResultCode.FAILED.getMessage());
        }

        log.info("修改成功. user.id = " + user.getId());
    }

    @Override
    public void modifyPassword(Long id, String oldPassword, String newPassword) {
        //  1. 参数校验
        if(id == null || id <= 0 || StringUtil.isEmpty(oldPassword) ||
                                    StringUtil.isEmpty(newPassword)) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE.getMessage());
        }
        User user = userMapper.selectByPrimaryKey(id);
        if(user == null || user.getDeleteState() == 1) {
            log.warn(ResultCode.AILED_USER_EXISTS.toString());
            throw new ApplicationException(ResultCode.AILED_USER_EXISTS.getMessage());
        }

        //  2. 检验输入与老密码是否相同
        if (!MD5Util.verifyOriginalAndCiphertext(oldPassword,user.getSalt(),user.getPassword())) {
            log.warn(ResultCode.FAILED_PWD_NOT_SAME.toString());
            throw new ApplicationException(ResultCode.FAILED_PWD_NOT_SAME.getMessage());
        }

        //  3. 生成新密文
        String salt = UUIDUtil.uuid_32();
        String encryptPassword = MD5Util.md5Salt(newPassword,salt);

        //  4. 组装数据
        User updateUser = new User();
        updateUser.setId(id);
        updateUser.setSalt(salt);
        updateUser.setPassword(encryptPassword);
        updateUser.setUpdateTime(new Date());

        //  5. 调用mapper
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        if(row != 1) {
            log.warn(ResultCode.FAILED.toString() + ". 更新密码失败");
            throw new ApplicationException(ResultCode.FAILED.getMessage());
        }

        log.info("更新密码成功. user.id = " + user.getId());
    }

    @Override
    public void modifyAvatarUrl(Long id,MultipartFile file) {
        //  1. 参数校验
        if(file == null) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE.getMessage());
        }
        User user = userMapper.selectByPrimaryKey(id);
        if(user == null || user.getDeleteState() == 1) {
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            throw new ApplicationException(ResultCode.FAILED_USER_NOT_EXISTS.getMessage());
        }

        //  2. 保存文件
        //  2.1 获取文件后缀名
        String fileType = file.getOriginalFilename().
                substring((file.getOriginalFilename().lastIndexOf(".")));
        //  2.2 新文件名
        String fileName = "/" + UUID.randomUUID() + fileType;


        //  3. 组装数据
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setAvatarUrl(fileName);
        updateUser.setUpdateTime(new Date());

        //todo 使用云服务器存储图片

        //  4. 调用mapper
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        if(row != 1) {
            log.warn(ResultCode.FAILED + ". 更新头像失败");
            throw new ApplicationException(ResultCode.FAILED.getMessage());
        }

        //  保存文件
        String filePath = avatarPath + fileName;
        try {
            file.transferTo(new File(filePath));
        } catch (IOException e) {
            e.printStackTrace();
            log.warn("上传失败! filePath = " + filePath);
        }
        log.info("上传成功. filePath = " + filePath);
    }
}
